﻿Imports System
Imports System.CodeDom
Imports System.Globalization
Imports System.Reflection

Namespace System.Workflow.ComponentModel
    Friend Class DelegateTypeInfo
        ' Methods
        Friend Sub New(ByVal delegateClass As Type)
            Me.Resolve(delegateClass)
        End Sub

        Public Overrides Function Equals(ByVal other As Object) As Boolean
            If (other Is Nothing) Then
                Return False
            End If
            Dim info As DelegateTypeInfo = [TryCast](other,DelegateTypeInfo)
            If (info Is Nothing) Then
                Return False
            End If
            If ((Me.ReturnType.BaseType <> info.ReturnType.BaseType) OrElse (Me.Parameters.Length <> info.Parameters.Length)) Then
                Return False
            End If
            Dim i As Integer
            For i = 0 To Me.Parameters.Length - 1
                Dim expression As CodeParameterDeclarationExpression = info.Parameters(i)
                If (expression.Type.BaseType <> Me.Parameters(i).Type.BaseType) Then
                    Return False
                End If
            Next i
            Return True
        End Function

        Public Overrides Function GetHashCode() As Integer
            Return MyBase.GetHashCode
        End Function

        Private Sub Resolve(ByVal method As MethodInfo)
            Dim parameters As ParameterInfo() = method.GetParameters
            Me.parameters = New CodeParameterDeclarationExpression(parameters.Length  - 1) {}
            Me.parameterTypes = New Type(parameters.Length  - 1) {}
            Dim i As Integer
            For i = 0 To parameters.Length - 1
                Dim name As String = parameters(i).Name
                Dim parameterType As Type = parameters(i).ParameterType
                If ((name Is Nothing) OrElse (name.Length = 0)) Then
                    name = ("param" & i.ToString(CultureInfo.InvariantCulture))
                End If
                Dim in As FieldDirection = FieldDirection.In
                If parameterType.IsByRef Then
                    If parameterType.FullName.EndsWith("&") Then
                        parameterType = parameterType.Assembly.GetType(parameterType.FullName.Substring(0, (parameterType.FullName.Length - 1)), True)
                    End If
                    [in] = FieldDirection.Ref
                End If
                If parameters(i).IsOut Then
                    If parameters(i).IsIn Then
                        [in] = FieldDirection.Ref
                    Else
                        [in] = FieldDirection.Out
                    End If
                End If
                Me.parameters(i) = New CodeParameterDeclarationExpression(New CodeTypeReference(parameterType), name)
                Me.parameters(i).Direction = [in]
                Me.parameterTypes(i) = parameterType
            Next i
            Me.returnType = New CodeTypeReference(method.ReturnType)
        End Sub

        Private Sub Resolve(ByVal delegateClass As Type)
            Dim method As MethodInfo = delegateClass.GetMethod("Invoke")
            If (method Is Nothing) Then
                Throw New ArgumentException("delegateClass")
            End If
            Me.Resolve(method)
        End Sub


        ' Properties
        Friend ReadOnly Property Parameters As CodeParameterDeclarationExpression()
            Get
                Return Me.parameters
            End Get
        End Property

        Friend ReadOnly Property ParameterTypes As Type()
            Get
                Return Me.parameterTypes
            End Get
        End Property

        Friend ReadOnly Property ReturnType As CodeTypeReference
            Get
                Return Me.returnType
            End Get
        End Property


        ' Fields
        Private parameters As CodeParameterDeclarationExpression()
        Private parameterTypes As Type()
        Private returnType As CodeTypeReference
    End Class
End Namespace

